// 封装一个ref函数
function ref(val) {
    // 在ref函数内部创建包裹对象
    const wrapper = {
        value: val
    }

    // Object.defineProperty 在wrapper对象上定义一个不可枚举的属性__v_isRef,并且值为true
    Object.defineProperty(wrapper, '__v_isRef', {
        value: true
    })
    // 将包裹对象变成响应式数据
    return reactive(wrapper)
}

/**
 * 
 * @param {*} obj 响应式数据
 * @param {*} key obj对象的一个键
 * @returns 一个类似于ref结构的对象
 */
function toRef(obj, key) {
    const wrapper = {
        get value() {
            return obj[key]
        },
        set value(val) {
            obj[key] = val
        }
    }
    // 定义__v_isRef 这样会将通过toRef或者toRefs转换后得到的结果视为真正的ref数据
    Object.defineProperty(wrapper, '__v_isRef', {
        value: true
    })
    return wrapper
}

function toRefs(obj) {
    const ret = {}
    for (const key in obj) {
        ret[key] = toRef(obj, key)
    }
    return ret
}

// 自动脱ref
function proxyRefs(target) {
    return new Proxy(target, {
        get(target, key, receiver) {
            const value = Reflect.get(target, key, receiver)
            // 如果读取的值是ref结构，返回它的value属性值，否则返回value自身
            return value.__v_isRef ? value.value : value
        },
        set(target, key, newVal, receiver) {
            const value = target[key]
            // 如果设置的属性是一个ref,那么我们间接设置ref的value属性的值
            if (value.__v_isRef) {
                value.value = newVal
                return true
            }
            return Reflect.set(target, key, newVal, receiver)
        }
    })
}